 /**
  * Copyright 2013 J. Miguel P. Tavares
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  ***************************************************************************/
package it.polimi.deib.se2.meteocal.business.control;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.util.Locale;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

/** Implements a synchronous HTTP client to the Open Weather Map service described
 * in http://openweathermap.org/wiki/API/JSON_API
 * @author mtavares */
public class DataWeatherImport{
    static private final String APPID_HEADER = "x-api-key";
    
    static public enum HistoryType {
        UNKNOWN,
        TICK, HOUR, DAY
    }
    
    private String baseOwmUrl = "http://api.openweathermap.org/data/2.5/";
    private String owmAPPID = null;
    
    private HttpClient httpClient;
    
    
    public DataWeatherImport () {
        this.httpClient = new DefaultHttpClient ();
    }
    
    public DataWeatherImport (HttpClient httpClient) {
        if (httpClient == null)
            throw new IllegalArgumentException ("Can't construct a OwmClient with a null HttpClient");
        this.httpClient = httpClient;
    }
    
    /**
     * @param appid */
    public void setAPPID (String appid) {
        this.owmAPPID = appid;
    }
    
    
    /*
    /** Find current city weather
    * @param cityName is the name of the city
    * @throws JSONException if the response from the OWM server can't be parsed
    * @throws IOException if there's some network error or the OWM server replies with a error. */
//	public WeatherStatusResponse currentWeatherAtCity (String cityName) throws IOException, JSONException {
//		String subUrl = String.format (Locale.ROOT, "find/name?q=%s", cityName);
//		JSONObject response = doQuery (subUrl);
//		return new WeatherStatusResponse (response);
//	}
    
    public int[] forecastWeatherAtCity (String cityName) throws JSONException, IOException {
        String subUrl;
        JSONObject element, response, weatherElement;
        int[] weatherCodeBis = new int[16];
        
        
        String cityNameCorrected = cityName.replace(" ","%20");
        
        subUrl = String.format (Locale.ROOT, "forecast/daily?q=%s&type=json&units=metric&cnt=16", cityNameCorrected);
        
        try{
            response = doQuery (subUrl);
            for(int i=0; i<16; i++){
               element = response.getJSONArray("list").getJSONObject(i);
            weatherElement = element.getJSONArray("weather").getJSONObject(0);
            weatherCodeBis[i] = Integer.parseInt(weatherElement.getString("id")); 
            }
            
        }catch(JSONException e){
            for(int i=0; i<16; i++){
                weatherCodeBis[i] = -1;
            }
        }
        
        
        
        return weatherCodeBis;
    }
    
    
    
    /** Get the weather forecast for a city
     * @param cityName is the Name of the city
     * @throws JSONException if the response from the OWM server can't be parsed
     * @throws IOException if there's some network error or the OWM server replies with a error. */
//	public WeatherForecastResponse forecastWeatherAtCity (String cityName) throws JSONException, IOException {
//		String subUrl = String.format (Locale.ROOT, "forecast/city?q=%s&type=json&units=metric", cityName);
//		JSONObject response = doQuery (subUrl);
//                response.getJSONArray(subUrl)
//		return new WeatherForecastResponse (response);
//	}
    
    
    
    private JSONObject doQuery (String subUrl) throws JSONException, IOException {
        String responseBody = null;
        HttpGet httpget = new HttpGet (this.baseOwmUrl + subUrl);
        if (this.owmAPPID != null) {
            httpget.addHeader (DataWeatherImport.APPID_HEADER, this.owmAPPID);
        }
        
        HttpResponse response = this.httpClient.execute (httpget);
        InputStream contentStream = null;
        try {
            StatusLine statusLine = response.getStatusLine ();
            if (statusLine == null) {
                throw new IOException (
                        String.format ("Unable to get a response from OWM server"));
            }
            int statusCode = statusLine.getStatusCode ();
            if (statusCode < 200 && statusCode >= 300) {
                throw new IOException (
                        String.format ("OWM server responded with status code %d: %s", statusCode, statusLine));
            }
            /* Read the response content */
            HttpEntity responseEntity = response.getEntity ();
            contentStream = responseEntity.getContent ();
            Reader isReader = new InputStreamReader (contentStream);
            int contentSize = (int) responseEntity.getContentLength ();
            if (contentSize < 0)
                contentSize = 8*1024;
            StringWriter strWriter = new StringWriter (contentSize);
            char[] buffer = new char[8*1024];
            int n = 0;
            while ((n = isReader.read(buffer)) != -1) {
                strWriter.write(buffer, 0, n);
            }
            responseBody = strWriter.toString ();
            contentStream.close ();
        } catch (IOException e) {
            throw e;
        } catch (RuntimeException re) {
            httpget.abort ();
            throw re;
        } finally {
            if (contentStream != null)
                contentStream.close ();
        }
        return new JSONObject (responseBody);
    }
}